package cn.uncode.dal.springboot.configuration;

import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import cn.uncode.dal.datasource.DynamicDataSource;
import cn.uncode.dal.router.SharingType;
import cn.uncode.dal.router.TableRouter;
import cn.uncode.dal.router.TableShardingRouter;
import cn.uncode.dal.springboot.config.ClusterDataSourceConfig;
import cn.uncode.dal.springboot.config.ClusterDataSourceProperties;
import cn.uncode.dal.springboot.config.CustomDataSourceConfig;
import cn.uncode.dal.springboot.config.MasterDataSourceConfig;
import cn.uncode.dal.springboot.config.SlavesDataSourceConfig;
import cn.uncode.dal.springboot.config.StandbyDataSourceConfig;
import cn.uncode.dal.springboot.config.UncodeDALShardingConfig;

/**
 * Created by juny on 2017/2/28 14:11
 */
@Configuration
@EnableConfigurationProperties({MasterDataSourceConfig.class, CustomDataSourceConfig.class,
	StandbyDataSourceConfig.class, SlavesDataSourceConfig.class, UncodeDALShardingConfig.class, ClusterDataSourceConfig.class})
@ConditionalOnClass(DataSource.class)
public class DataSourceAutoConfiguration {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceAutoConfiguration.class);
	
	@Autowired
	private MasterDataSourceConfig masterConfig;
	
	@Autowired
	private StandbyDataSourceConfig standbyConfig;
	
	@Autowired
	private SlavesDataSourceConfig slavesConfig;
	
	@Autowired
	private UncodeDALShardingConfig uncodeDALShardingConfig;
	
	@Autowired
	private CustomDataSourceConfig customConfig;
	
	@Autowired
	private ClusterDataSourceConfig clusterConfig;
	
	@Autowired
	private Environment env;
	
	@Bean
	public DataSource uncodeDataSource(){
		initClusterDataSource();
		DynamicDataSource dynamicDataSource = new DynamicDataSource();
		//默认库为主库
		dynamicDataSource.setResolvedMasterDataSource(this.masterConfig.build());
		dynamicDataSource.setResolvedStandbyDataSource(standbyConfig.build());
		dynamicDataSource.setResolvedSlaveDataSources(slavesConfig.build());
		dynamicDataSource.getCustomDataSources().putAll(customConfig.build());
		if(uncodeDALShardingConfig != null && uncodeDALShardingConfig.getTable() != null){
			int len = uncodeDALShardingConfig.getTable().size();
			for(int i=0; i<len; i++){
				String table = uncodeDALShardingConfig.getTable().get(i);
				String type = uncodeDALShardingConfig.getType().get(i);
				String field = uncodeDALShardingConfig.getField().get(i);
				String value = uncodeDALShardingConfig.getValue().get(i);
				String indexTableFields = uncodeDALShardingConfig.getIndexTableFields().get(i);
				TableRouter tableRouter = new TableRouter();
				tableRouter.setTableName(table);
				if(SharingType.RANGE.TYPE.equals(type)){
					tableRouter.setSharingType(SharingType.RANGE);
				}else if(SharingType.HASH.TYPE.equals(type)){
					tableRouter.setSharingType(SharingType.HASH);
				}else if(SharingType.CUSTOM.TYPE.equals(type)){
					tableRouter.setSharingType(SharingType.CUSTOM);
				}
				if(StringUtils.isNotEmpty(field)){
					tableRouter.setFieldName(field);
				}
				if(StringUtils.isNotEmpty(value)){
					//cn.uncode.strategy.MyStrategy
					if(SharingType.CUSTOM.equals(tableRouter.getSharingType())){
						tableRouter.setClazz(value);
					}
				}
				if(StringUtils.isNotEmpty(indexTableFields)){
					String[] fds = indexTableFields.split(",");
					tableRouter.setIndexTableFields(fds);
				}
				TableShardingRouter.setTableRouter(table, tableRouter);
			}
				
				
		}
	
		LOGGER.info("===Uncode-Dal===DataSourceAutoConfiguration===>DynamicDataSource inited..");
		return dynamicDataSource;
	}
	
	private void initClusterDataSource() {
		if(clusterConfig != null) {
			if(null != clusterConfig.getClusters()) {
				for(ClusterDataSourceProperties item : clusterConfig.getClusters()) {
					if(StringUtils.isNotBlank(item.getName()) && item.getName().equals(getAppName())){
						if(StringUtils.isNotBlank(item.getType())) {
							String[] array = item.getType().split(",");
							for(String type:array) {
								if("master".equals(type)) {
									masterConfig.valueOf(item);
								}else if("standby".equals(type)) {
									standbyConfig.valueOf(item);
								}else if("slave".equals(type)) {
									slavesConfig.add(item);
								}
							}
						}
					}
				}
			}
		}
	}
	
	private String getAppName() {
		String appName = env.getProperty("spring.application.name");
		if(StringUtils.isBlank(appName)) {
			appName = env.getProperty("app.name");
		}
		if(StringUtils.isBlank(appName)) {
			appName = env.getProperty("app.id");
		}
		return appName;
	}
}
